package top.hmtools.manager.asynchronous;

import java.util.Observable;
import java.util.concurrent.ThreadPoolExecutor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import top.hmtools.RLContext;
import top.hmtools.autoConfiguration.RequestLoggerAutoConfiguration;

/**
 * 执行将用户请求日志缓存队列数据写入数据库的功能守护线程。此线程通过观察者模式保证挂了也能够自动重启。 
 * 本对象使用了线程池，故 本代码类主要用于对 线程池 与 具体执行写入数据库操作的线程 的调度
 * @author HyboJ
 *
 */
public class ThreadBoss extends Observable implements Runnable{
	
	protected final Logger logger = LoggerFactory.getLogger(ThreadBoss.class);
	
	private RLContext rlContext;
	
	public ThreadBoss(RLContext rlContext){
		this.rlContext = rlContext;
	}
	
	@Override
	public void run() {
		while(true){
			RequestLoggerAutoConfiguration requestLoggerAutoConfiguration = rlContext.requestLoggerAutoConfiguration;//全局配置
			boolean asynchronous = requestLoggerAutoConfiguration.isAsynchronous();//是否异步（配置值）
			int batchItemSize = requestLoggerAutoConfiguration.getBatchItemSize();//单批次写入数据库最大条目数（配置值）
			int poolWorkQueueSize = requestLoggerAutoConfiguration.getPoolWorkQueueSize();//最大线程缓存容量（配置值）
			int currPoolQueueSize = this.rlContext.threadPoolExecutor.getQueue().size();//线程池当前已用缓存数量
			
			//用户请求的主要日志信息
			try {
				int queueSize = this.rlContext.requestLogBeanQueue.getQueueSize();//缓存队列现有数据量
				
				//当配置的写入数据库方式为异步 且 当前缓存中数据数量大于配置的阀值 且 当前线程池中队里排队数小于配置的最大队列数时，执行
				if(asynchronous && queueSize>=batchItemSize && currPoolQueueSize < poolWorkQueueSize){
					ThreadPoolExecutor threadPoolExecutor = this.rlContext.threadPoolExecutor;
					ThreadWorker threadWorker = new ThreadWorker(this.rlContext);
					threadPoolExecutor.execute(threadWorker);
				}else{
					//TODO 线程休眠策略
					Thread.sleep(1000);
				}
			} catch (Exception e) {
				e.printStackTrace();
				logger.error("执行将用户请求日志缓存队列数据写入数据库的功能守护线程发生异常："+e.getMessage(),e);
			}
			
			//追加的用户请求的扩展日志信息，比如：用户页面停留时间
			try {
				int queueSize = this.rlContext.requestLogBeanExtraQueue.getQueueSize();
				
				//当配置的写入数据库方式为异步 且 当前缓存中数据数量大于配置的阀值 且 当前线程池中队里排队数小于配置的最大队列数时，执行
				if(asynchronous && queueSize>=batchItemSize && currPoolQueueSize < poolWorkQueueSize){
					ThreadPoolExecutor threadPoolExecutor = this.rlContext.threadPoolExecutor;
					ThreadWorkerExtra threadWorkerExtra = new ThreadWorkerExtra(this.rlContext);
					threadPoolExecutor.execute(threadWorkerExtra);
				}else{
					//TODO 线程休眠策略
					Thread.sleep(1000);
				}
			} catch (Exception e) {
				// TODO: handle exception
			}
		}
			
	}

}
